package rabbitas{
	import rabbitas.ns.Nodes;
	import flash.events.IEventDispatcher;
	import rabbitas.attributes.AttributeName;
	import rabbitas.util.PropUtil;
	import flash.system.ApplicationDomain;
	import rabbitas.util.IRabbitASUtil;
	import flash.net.getClassByAlias;

	/**
	 * @author martindyrby
	 */
	public class InstanceCreator {
		private static const ADD_CHILD : String = "addChild";
		private static const ADD_CHILD_DATA : String = "addChildData";
		
		private var aliasName:String;
		private var clazz: Class;

		public var instanceManager : InstanceManager;
		public var instanceDecorator : InstanceDecorator;
		public var eventManager:EventManager;
		public var autoWireManager:AutoWireManager;

		public function InstanceCreator() {
		}

		public function createFromXML(def : XML) : * {
			aliasName = Reflector.reflectStringValue(def.@type, instanceManager);
			
			try {
				clazz = getClassByAlias(aliasName) as Class;	
			} catch(e : Error) {
				clazz = ApplicationDomain.currentDomain.getDefinition(aliasName) as Class;
			}
			
			if(def.name()==Nodes.staticQName.localName) return clazz;

			var params:Array = [];
			
			var constructorList:XMLList = def.child(Nodes.constructorQName);

			if(constructorList.length()>0){
				var paramsList:XMLList=def.child(Nodes.constructorQName).child(Nodes.paramQName);
				
				for(var i:int=0; i<paramsList.length(); i++){
					params[i]=Reflector.reflectStringValue(paramsList[i].text().toString(),instanceManager);
				}
			}
			
			
			var instance : *;
			
			switch(params.length){
				
				case 0:
					instance = new clazz();
					break;
				case 1:
					instance = new clazz(params[0]);
					break;
				case 2:
					instance = new clazz(params[0],params[1]);
					break;
				case 3:
					instance = new clazz(params[0],params[1],params[2]);
					break;
				case 4:
					instance = new clazz(params[0],params[1],params[2],params[3]);
					break;
				case 5:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4]);
					break;
				case 6:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5]);
					break;
				case 7:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6]);
					break;
				case 8:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7]);
					break;
				case 9:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]);
					break;
				case 10:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9]);
					break;
				case 11:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10]);
					break;
				case 12:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11]);
					break;
				case 13:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12]);
					break;
				case 14:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13]);
					break;
				case 15:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13],params[14]);
					break;
				case 16:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13],params[14],params[15]);
					break;
				case 17:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13],params[14],params[15],params[16]);
					break;
				case 18:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13],params[14],params[15],params[16],params[17]);
					break;
				case 19:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13],params[14],params[15],params[16],params[17],params[18]);
					break;
				case 20:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13],params[14],params[15],params[16],params[17],params[18],params[19]);
					break;
				case 21:
					instance = new clazz(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11],params[12],params[13],params[14],params[15],params[16],params[17],params[18],params[19],params[20]);
					break;
				default:
					throw new ArgumentError(params.length + " is to many parameters for a construtor in Rabbit.");
					break;
			}
			

			if(instance is IRabbitASUtil) return IRabbitASUtil(instance).value;
			
			return instance;		
		}
		
		public function decorate(def:XML,instance:*):void{
			instanceDecorator.decorateFromAttributes(def, instance);
						
			instanceDecorator.decorateFromChildren(def, instance);
			
			autoWireManager.autoWireInstance(instance);

			if(instance is IEventDispatcher) {
				eventManager.setupEvents(def, instance);
			}			
		}
	}
}
